package com.xgk.boot.module.core.logistics.service;


import cn.hutool.core.util.StrUtil;
import com.xgk.boot.framework.common.constant.ErrorCodeConstants;
import com.xgk.boot.framework.common.exception.util.ServiceExceptionUtil;
import com.xgk.boot.module.core.common.RedisHandlerService;
import com.xgk.boot.module.core.dal.dto.TruckOrderDto;
import com.xgk.boot.module.core.dal.entity.channel.ApiServiceDO;
import com.xgk.boot.module.core.dal.entity.channel.ServiceProviderDO;
import com.xgk.boot.module.core.dal.entity.product.ProductDO;
import com.xgk.boot.module.core.dal.redis.RedisKeyConstants;
import com.xgk.boot.module.core.logistics.common.LogisticsCache;
import com.xgk.boot.module.core.logistics.inter.ShippingService;
import com.xgk.boot.module.core.logistics.service.dto.RespOrderDto;
import com.xgk.boot.module.core.logistics.service.dto.RespRateDto;
import com.xgk.boot.module.core.logistics.service.mothership.response.OrderDto;
import com.xgk.boot.module.core.logistics.service.mothership.response.RateDto;
import com.xgk.boot.module.core.service.channel.ServiceProviderAPIServiceImpl;
import com.xgk.boot.module.core.service.channel.ServiceProviderServiceImpl;
import com.xgk.boot.module.core.service.product.ProductServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 实现类编码，这个code是和物流服务商的code保持一致的
 * 一个物流服务商可能存在多个api类（对应的token、 ak/sk/ url等可能不同）
 * 通过订单的商品code计算出对应的真实物流服务API类，触发调用
 */
@Slf4j
@Service
public class TruckShipperChannelService {

    @Resource
    private ProductServiceImpl productService;
    @Resource
    private ServiceProviderAPIServiceImpl spApiService;
    @Resource
    private ServiceProviderServiceImpl spService;
    @Resource
    private RedisHandlerService redisHandlerService;

    /**
     * 根据shipperCode获取运输服务实现类
     */
    public ShippingService getShippingService(String shipperCode) {
        if(StrUtil.isBlank(shipperCode)) {
            log.error("shipperCode不能为空");
            throw  ServiceExceptionUtil.exception(ErrorCodeConstants.PRODUCT_CHANNEL_EXISTS,"shipperService");
        }
        // 这里可以根据shipperCode从缓存或其他数据源获取对应的运输服务实现类
        ShippingService shippingService = LogisticsCache.SHIPPING_CODE_MAP.get(shipperCode);
        if(shippingService != null) {
            log.info("获取到运输服务实现类，shipperCode: {}", shipperCode);
            return shippingService;
        }
        log.info("未获取到运输服务实现类，shipperCode: {}", shipperCode);
        throw  ServiceExceptionUtil.exception(ErrorCodeConstants.PRODUCT_CHANNEL_EXISTS,"shipperService");
    }

    /**
     * 根据产品code获取对应的spi配置
     */
    private ApiServiceDO getApiServiceByProductCode(String logisticsProductCode) {
        // 这里可以根据logisticsProduct从缓存或其他数据源获取对应的shipperCode
        log.debug("获取shipperCode，logisticsProduct: {}", logisticsProductCode);
        ApiServiceDO apiServiceDO = productService.getApiServiceByProductCode(logisticsProductCode);
        return apiServiceDO;
    }

    /**
     * 设置物流服务商code
     * @param orderInfo
     */
    private void setSpApiServiceCode(TruckOrderDto orderInfo){
        if(StrUtil.isNotBlank(orderInfo.getShipperCode())){
            return;
        }
//        String spCode = orderInfo.getTruckOrdersDO().getSpCode();
//        if(StrUtil.isNotBlank(spCode)){
//            // 设置物流服务商code
//            orderInfo.setShipperCode(spCode);
//            return;
//        }
        ProductDO product = productService.getProductCacheByCode(orderInfo.getTruckOrdersDO().getProductCode());
        if(product == null) {
            log.error("未找到对应的物流产品，productCode: {}", orderInfo.getTruckOrdersDO().getProductCode());
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.COMMON_INFO_EXISTS, "logisticsProduct");
        }
        ServiceProviderDO byId = spService.getById(product.getPrSpId());
        // 设置物流服务商code
        orderInfo.setShipperCode(byId.getSpCode());
    }


    private void setApiService(TruckOrderDto orderInfo) {
        if(orderInfo.getApiServiceDO() != null) {
            log.debug("订单已包含apiService信息，直接返回: {}", orderInfo.getApiServiceDO());
            return ;
        }
        ApiServiceDO apiServiceByProductCode = getApiServiceByProductCode(orderInfo.getTruckOrdersDO().getProductCode());
        orderInfo.setApiServiceDO(apiServiceByProductCode);
    }


    /**
     * 获取物流报价列表
     */
    public List<RateDto> getLogisticsQuotationList(TruckOrderDto orderInfo) throws IOException {
        preCheck(orderInfo);
        ShippingService shippingService = getShippingService(orderInfo.getShipperCode());

        RespRateDto orderQuotation = shippingService.getOrderQuotation(orderInfo);
        if(orderQuotation!=null && orderQuotation.getCode().equals("200")){
            if(orderQuotation.getWarnings()!=null && orderQuotation.getWarnings().size() > 0){
                redisHandlerService.set(String.format(RedisKeyConstants.QUOTATION_KEY_WARNING,orderQuotation.getResponseId()),orderQuotation.getWarnings(),
                        30, TimeUnit.MINUTES);
            }
            return orderQuotation.getRates();
        }
        String msg = orderQuotation != null ? orderQuotation.getErrorMessage() : "unknow error";
        log.error("获取服务商物流报价失败，错误信息: {}", msg);
        throw ServiceExceptionUtil.exception(ErrorCodeConstants.REQUEST_QUOTATION_EXCEPTION, msg);
    }

    /**
     * 根据选择的物流报价进行下单
     */
    public OrderDto createLogisticsOrder(TruckOrderDto orderInfo) throws IOException {
        preCheck(orderInfo);
        ShippingService shippingService = getShippingService(orderInfo.getShipperCode());

        RespOrderDto order = shippingService.createOrder(orderInfo);
        if(order!=null && order.getCode().equals("200")){
            return order.getOrderDto();
        }
        String msg = order != null ? order.getErrorMessage() : "unknow error";
        log.error("服务商同步订单异常，错误信息: {}", msg);
        throw ServiceExceptionUtil.exception(ErrorCodeConstants.REQUEST_CREATE_ORDER_EXCEPTION, msg);
    }

    /**
     * 获取订单状态
     */
    public Object getLogisticsOrderStatus(TruckOrderDto orderInfo) {
        preCheck(orderInfo);
        ShippingService shippingService = getShippingService(orderInfo.getShipperCode());
        return shippingService.getOrderStatus(orderInfo);
    }

    /**
     * 获取订单内容
     */
    public OrderDto getLogisticsOrderDetail(TruckOrderDto orderInfo) throws IOException {
        preCheckNotAddress(orderInfo);
        ShippingService shippingService = getShippingService(orderInfo.getShipperCode());
        RespOrderDto order = shippingService.getOrderDetail(orderInfo);
        if(order!=null && order.getCode().equals("200")){
            return order.getOrderDto();
        }
        String msg = order != null ? order.getErrorMessage() : "unknow error";
        log.error("获取服务商订单信息异常，错误信息: {}", msg);
        throw ServiceExceptionUtil.exception(ErrorCodeConstants.REQUEST_ORDER_INFO_EXCEPTION, msg);
    }

    /**
     * 获取物流信息
     */
    public OrderDto getLogisticsOrderTracking(TruckOrderDto orderInfo)  throws IOException {
        preCheckNotAddress(orderInfo);
        ShippingService shippingService = getShippingService(orderInfo.getShipperCode());
        RespOrderDto orderTracking = shippingService.getOrderTracking(orderInfo);
        if(orderTracking!=null && orderTracking.getCode().equals("200")){
            return orderTracking.getOrderDto();
        }
        String msg = orderTracking != null ? orderTracking.getErrorMessage() : "unknow error";
        log.error("获取服务商订单物流信息异常，错误信息: {}", msg);
        throw ServiceExceptionUtil.exception(ErrorCodeConstants.REQUEST_ORDER_TRACK_EXCEPTION, msg);
    }

    /**
     * 获取提单信息
     */
    public OrderDto getLogisticsOrderBols(TruckOrderDto orderInfo)  throws IOException {
        preCheckNotAddress(orderInfo);
        ShippingService shippingService = getShippingService(orderInfo.getShipperCode());
        RespOrderDto respOrder = shippingService.getOrderBol(orderInfo);
        if(respOrder!=null && respOrder.getCode().equals("200")){
            return respOrder.getOrderDto();
        }
        String msg = respOrder != null ? respOrder.getErrorMessage() : "unknow error";
        log.error("获取服务商订单物流信息异常，错误信息: {}", msg);
        throw ServiceExceptionUtil.exception(ErrorCodeConstants.REQUEST_ORDER_TRACK_EXCEPTION, msg);
    }

    /**
     * 取消订单
     */
    public Object cancelLogisticsOrder(TruckOrderDto orderInfo) {
        preCheck(orderInfo);
        ShippingService shippingService = getShippingService(orderInfo.getShipperCode());
        return shippingService.cancelOrder(orderInfo);
    }


    /**
     * 调用相关物流api实现接口前置检查
     * 1、检查是否有物流订单主表信息
     * 2、检查是否有物流对应api配置信息
     * @param orderInfo
     */
    private void preCheck(TruckOrderDto orderInfo){
        if (orderInfo == null || orderInfo.getTruckOrdersDO() == null) {
            log.error("订单信息不能为空");
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.COMMON_INFO_EXISTS, "orderInfo");
        }
        if (orderInfo.getTruckOrdersDO().getProductCode() == null) {
            log.error("订单信息中缺少物流产品代码");
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.COMMON_INFO_EXISTS, "logisticsProductCode");
        }
        setSpApiServiceCode(orderInfo);
        setApiService(orderInfo);
    }


    private void preCheckNotAddress(TruckOrderDto orderInfo){
        setSpApiServiceCode(orderInfo);
        setApiService(orderInfo);
    }



}
